package com.jichangxiu.generator.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.jichangxiu.common.annotation.Dynamic;
import com.jichangxiu.common.exception.ServiceException;
import com.jichangxiu.common.utils.ConvertUtils;
import com.jichangxiu.generator.entity.bo.GenTemplateBo;
import com.jichangxiu.generator.entity.dto.add.AddGenTemplate;
import com.jichangxiu.generator.entity.dto.edit.EditGenTemplate;
import com.jichangxiu.generator.entity.dto.query.QueryGenTemplate;
import com.jichangxiu.generator.entity.po.GenTemplate;
import com.jichangxiu.generator.entity.vo.GenTemplateVo;
import com.jichangxiu.generator.mapper.GenTemplateMapper;
import com.jichangxiu.generator.service.GenTemplateService;
import com.jichangxiu.framework.utils.SecurityUtils;
import com.jichangxiu.framework.utils.NoUtils;
import com.jichangxiu.common.entity.bo.ValidateBos;
import com.jichangxiu.framework.service.impl.BaseServiceImpl;
import com.jichangxiu.framework.utils.ValidateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * GenTemplateServiceImpl:
 *
 * @author JiChangXiu
 * @create 2024-06-30 13:31:07
 */
@Service
public class GenTemplateServiceImpl extends BaseServiceImpl<GenTemplateMapper, GenTemplate, GenTemplateVo> implements GenTemplateService {

    /**
     * 新增生成模板
     *
     * @param addGenTemplate 新增生成模板视图对象
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(AddGenTemplate addGenTemplate) {
        return getBaseMapper().insert(addAndEditValidBo(ConvertUtils.convert(addGenTemplate, GenTemplateBo.class))) > 0;
    }

    /**
     * 单（多）选删除生成模板
     *
     * @param idList 生成模板主键列表
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean del(List<String> idList) {
        return getBaseMapper().deleteBatchIds(delValid(idList)) > 0;
    }

    /**
     * 修改生成模板
     *
     * @param editGenTemplate 修改生成模板视图对象
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(EditGenTemplate editGenTemplate) {
        return getBaseMapper().updateById(addAndEditValidBo(ConvertUtils.convert(editGenTemplate, GenTemplateBo.class))) > 0;
    }

    /**
     * 根据主键查询生成模板
     *
     * @param id       生成模板主键
     * @param isExtend 是否扩展
     * @return 生成模板详情
     */
    @Dynamic
    @Override
    public GenTemplateVo info(@NotBlank(message = "主键不能为空") String id, Boolean isExtend) {
        GenTemplateVo genTemplateVo = getBaseMapper().selectJoinOne(GenTemplateVo.class, buildQueryWrapper(QueryGenTemplate.builder().id(id).build()));
        if (Boolean.TRUE.equals(isExtend) && ObjectUtil.isNotEmpty(genTemplateVo))
            genTemplateVo = renderGenTemplateVoList(ListUtil.toList(genTemplateVo)).get(0);
        return genTemplateVo;
    }

    /**
     * （可分页）查询生成模板列表
     *
     * @param queryGenTemplate 查询视图对象
     * @return （分页）生成模板列表
     */
    @Dynamic
    @Override
    public Page<GenTemplateVo> lists(QueryGenTemplate queryGenTemplate) {
        Page<GenTemplateVo> genTemplateVoPage = getBaseMapper().selectJoinPage(startPage(), GenTemplateVo.class, buildQueryWrapper(queryGenTemplate));
        if (Boolean.TRUE.equals(queryGenTemplate.getIsExtend()))
            genTemplateVoPage.setRecords(renderGenTemplateVoList(genTemplateVoPage.getRecords()));
        return genTemplateVoPage;
    }

    /**
     * 新增 / 修改 前校验
     *
     * @param genTemplateBo 校验用业务对象
     * @return 数据库操作对象
     */
    public GenTemplate addAndEditValidBo(GenTemplateBo genTemplateBo) {
        GenTemplate genTemplate = ConvertUtils.convert(genTemplateBo, GenTemplate.class);
        if (ObjectUtil.isNull(genTemplate))
            throw new ServiceException("待校验对象为空");
        List<ValidateBos> validateBosList = Stream.of(
                ValidateUtils.createNeValidateBos(ValidateUtils.createValidateBo(GenTemplate::getId, genTemplate.getId(), "主键")),
                ValidateUtils.createEqValidateBos(ValidateUtils.createValidateBo(GenTemplate::getCategoryId, genTemplate.getCategoryId(), "分类ID")),
                ValidateUtils.createOrEqValidateBos(
                        ValidateUtils.createValidateBo(GenTemplate::getNo, genTemplate.getNo(), "编码"),
                        ValidateUtils.createValidateBo(GenTemplate::getCode, genTemplate.getCode(), "标识"),
                        ValidateUtils.createValidateBo(GenTemplate::getName, genTemplate.getName(), "名称"),
                        ValidateUtils.createValidateBo(GenTemplate::getCategoryId, genTemplate.getCategoryId(), "分类ID"),
                        ValidateUtils.createValidateBo(GenTemplate::getRemark, genTemplate.getRemark(), "备注"))
        ).collect(Collectors.toList());
        // 唯一校验
        ValidateUtils.uniqueValidate(this::countWrapper, validateBosList);
        if (StrUtil.isEmpty(genTemplate.getId())) {
            // 新增
            genTemplate.setNo(NoUtils.createNo(SecurityUtils.getTenantId(), "template"));
            genTemplate.setTenantId(SecurityUtils.getTenantId());
            return genTemplate;
        } else {
            // 修改
            GenTemplate dbGenTemplate = getById(genTemplate.getId());
            BeanUtil.copyProperties(genTemplate, dbGenTemplate, true);
            return dbGenTemplate;
        }
    }

    /**
     * 删除前校验
     *
     * @param idList 主键列表
     * @return 主键列表
     */
    public List<String> delValid(List<String> idList) {
        if (ObjectUtil.isNull(idList))
            throw new ServiceException("待校验主键列表为空");
        return idList;
    }

    /**
     * 渲染视图
     *
     * @param genTemplateVoList 视图列表
     * @return 渲染后的视图列表
     */
    public List<GenTemplateVo> renderGenTemplateVoList(List<GenTemplateVo> genTemplateVoList) {
        if (ObjectUtil.isNotEmpty(genTemplateVoList)) {
            // todo 扩展信息填入
        }
        return genTemplateVoList;
    }

    /**
     * 构建查询条件
     *
     * @param queryGenTemplate 查询用业务对象
     * @return 查询条件
     */
    public MPJLambdaWrapper<GenTemplate> buildQueryWrapper(QueryGenTemplate queryGenTemplate) {
        MPJLambdaWrapper<GenTemplate> lambdaQueryWrapper = new MPJLambdaWrapper<GenTemplate>().selectAll(GenTemplate.class);
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenTemplate.getId()), GenTemplate::getId, queryGenTemplate.getId());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenTemplate.getNo()), GenTemplate::getNo, queryGenTemplate.getNo());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(queryGenTemplate.getCode()), GenTemplate::getCode, queryGenTemplate.getCode());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(queryGenTemplate.getName()), GenTemplate::getName, queryGenTemplate.getName());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenTemplate.getType()), GenTemplate::getType, queryGenTemplate.getType());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenTemplate.getContent()), GenTemplate::getContent, queryGenTemplate.getContent());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenTemplate.getCategoryId()), GenTemplate::getCategoryId, queryGenTemplate.getCategoryId());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(queryGenTemplate.getSort()), GenTemplate::getSort, queryGenTemplate.getSort());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(queryGenTemplate.getRemark()), GenTemplate::getRemark, queryGenTemplate.getRemark());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(queryGenTemplate.getEnabled()), GenTemplate::getEnabled, queryGenTemplate.getEnabled());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenTemplate.getEnabledBy()), GenTemplate::getEnabledBy, queryGenTemplate.getEnabledBy());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(queryGenTemplate.getEnabledTime()), GenTemplate::getEnabledTime, queryGenTemplate.getEnabledTime());
        return lambdaQueryWrapper;
    }

}